﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public class LogicContradiction : CanvasExpression
    {
        public LogicContradiction(SubPanel rootPanel, SubPanel parentPanel, Editor editor)
            : base(rootPanel, parentPanel, editor)
        {
            //绘制外接圆。
            outEllipse = new Ellipse();
            outEllipse.StrokeThickness = 2;
            outEllipse.Stroke = ExForeground;
            outEllipse.Fill = System.Windows.Media.Brushes.Transparent;
            outEllipse.Cursor = Cursors.Hand;
            outEllipse.MouseRightButtonDown += Ellipse_MouseRightButtonDown;
            outEllipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
            outEllipse.MouseLeftButtonUp += Ellipse_MouseLeftButtonUp;

            splitLine = new Line();
            splitLine.StrokeThickness = 2;
            splitLine.Stroke = ExForeground;
            splitLine.Fill = System.Windows.Media.Brushes.Transparent;
            splitLine.Cursor = Cursors.Hand;
            splitLine.MouseRightButtonDown += Ellipse_MouseRightButtonDown;

            leftEllipse = new Ellipse();
            leftEllipse.Visibility = Visibility.Hidden;
            leftEllipse.StrokeThickness = 2;
            leftEllipse.Stroke = ExForeground;
            leftEllipse.Fill = System.Windows.Media.Brushes.Transparent;
            leftEllipse.Cursor = Cursors.Hand;
            leftEllipse.MouseRightButtonDown += Ellipse_MouseRightButtonDown;
            leftEllipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
            leftEllipse.MouseLeftButtonUp += Ellipse_MouseLeftButtonUp;

            rightEllipse = new Ellipse();
            rightEllipse.Visibility = Visibility.Hidden;
            rightEllipse.StrokeThickness = 2;
            rightEllipse.Stroke = ExForeground;
            rightEllipse.Fill = System.Windows.Media.Brushes.Transparent;
            rightEllipse.Cursor = Cursors.Hand;
            rightEllipse.MouseRightButtonDown += Ellipse_MouseRightButtonDown;
            rightEllipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
            rightEllipse.MouseLeftButtonUp += Ellipse_MouseLeftButtonUp;

            basePanel.Children.Add(outEllipse);
            basePanel.Children.Add(splitLine);
            basePanel.Children.Add(leftEllipse);
            basePanel.Children.Add(rightEllipse);

            Canvas.SetZIndex(splitLine, 0);
            Canvas.SetZIndex(outEllipse, 1);
            Canvas.SetZIndex(leftEllipse, 2);
            Canvas.SetZIndex(rightEllipse, 3);

            //两个主面板。
            leftPanel = new SubPanel(rootPanel, parentPanel, editor, this);
            rightPanel = new SubPanel(rootPanel, parentPanel, editor, this);

            leftPanel.SizeChanged += eachPanel_SizeChanged;
            rightPanel.SizeChanged += eachPanel_SizeChanged;

            basePanel.Children.Add(leftPanel);
            basePanel.Children.Add(rightPanel);

            Canvas.SetZIndex(leftPanel, 101);
            Canvas.SetZIndex(rightPanel, 102);

            RefreshSubPanelRelatios();

            this.chineseName = "[矛盾/对立]式";
        }

        public override Brush ExForeground
        {
            get
            {
                return base.ExForeground;
            }
            set
            {
                UpdateExForegroundWithoutXmlChanging(value);
                UpdateExForegroundToXmlData(value);
                Editor.IsModified = true;
            }
        }

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            base.exForeground = value;
            this.splitLine.Stroke = value;
            this.outEllipse.Stroke = value;
            this.leftEllipse.Stroke = value;
            this.rightEllipse.Stroke = value;
        }

        void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            // 接收拖动来的公式。
            Globals.DropExpression(this);
        }

        void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //准备拖动公式。
            Globals.dragSourceExpression = this;
            this.Editor.SelectedExpression = this;
            e.Handled = true;
        }

        void Ellipse_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.Editor.SelectedExpression = this;
            e.Handled = true;
        }

        /// <summary>
        /// 外部大圆，表示“父范围”。
        /// </summary>
        private Ellipse outEllipse;

        /// <summary>
        /// 这两个小圆与分隔线不同时出现。
        /// </summary>
        private Ellipse leftEllipse;

        /// <summary>
        /// 这两个小圆与分隔线不同时出现。
        /// </summary>
        private Ellipse rightEllipse;

        /// <summary>
        /// 分开对立双方的分隔线。
        /// </summary>
        private Line splitLine;

        private bool isJustContradict = true;

        public bool IsJustContradict
        {
            get { return isJustContradict; }
            set
            {
                if (isJustContradict != value)
                {
                    isJustContradict = value;

                    if (isJustContradict)
                    {
                        splitLine.Visibility = Visibility.Visible;
                        leftEllipse.Visibility = Visibility.Hidden;
                        rightEllipse.Visibility = Visibility.Hidden;
                    }
                    else
                    {
                        splitLine.Visibility = Visibility.Hidden;
                        leftEllipse.Visibility = Visibility.Visible;
                        rightEllipse.Visibility = Visibility.Visible;
                    }

                    if (this.XmlData != null)
                    {
                        this.XmlData.SetAttribute("IsJustContradict", isJustContradict.ToString());
                    }

                    Editor.IsModified = true;
                }
            }
        }

        void eachPanel_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            // 重新计算BasePanel（Canvas）的尺寸。
            if (leftPanel == null || rightPanel == null) return;

            double maxDiameter = 0;
            double width, height;
            double leftDiameter, rightDiameter;

            width = leftPanel.ActualWidth; height = leftPanel.ActualHeight;
            leftDiameter = Math.Sqrt(width * width + height * height);
            if (maxDiameter < leftDiameter) maxDiameter = leftDiameter;

            width = rightPanel.ActualWidth; height = rightPanel.ActualHeight;
            rightDiameter = Math.Sqrt(width * width + height * height);
            if (maxDiameter < rightDiameter) maxDiameter = rightDiameter;
            // 已取出maxDiameter。

            double redius = maxDiameter / 2;//半径

            basePanel.Height = leftDiameter + rightDiameter + 40;// 上下各留空白10.

            basePanel.Width = leftDiameter + rightDiameter + 40;// 左右各留空白10，两个子面板之间留下对立关系所需要的空白20.

            basePanel.InvalidateArrange();
            basePanel.UpdateLayout();

            double halfWidth = basePanel.ActualWidth / 2;
            double halfHeight = basePanel.ActualHeight / 2;

            // 刷新各子面板位置。
            Point leftPt = new Point(15 + leftDiameter / 2, halfHeight);
            Point rightPt = new Point(basePanel.ActualWidth - 15 - rightDiameter / 2, halfHeight);

            Canvas.SetLeft(leftPanel, leftPt.X - leftPanel.ActualWidth / 2);
            Canvas.SetTop(leftPanel, leftPt.Y - leftPanel.ActualHeight / 2);

            Canvas.SetLeft(rightPanel, rightPt.X - rightPanel.ActualWidth / 2);
            Canvas.SetTop(rightPanel, rightPt.Y - rightPanel.ActualHeight / 2);

            // 重置外接圆与分隔线的位置、大小。
            outEllipse.Width = outEllipse.Height = basePanel.ActualWidth - 12;
            Canvas.SetLeft(outEllipse, 6);
            Canvas.SetTop(outEllipse, 6);

            leftEllipse.Width = leftEllipse.Height = leftDiameter + 8;
            Canvas.SetLeft(leftEllipse, leftPt.X - leftDiameter / 2 - 4);
            Canvas.SetTop(leftEllipse, leftPt.Y - leftDiameter / 2 - 4);

            rightEllipse.Width = rightEllipse.Height = rightDiameter + 8;
            Canvas.SetLeft(rightEllipse, rightPt.X - rightDiameter / 2 - 4);
            Canvas.SetTop(rightEllipse, rightPt.Y - rightDiameter / 2 - 4);

            double rOfOutEllipse = outEllipse.Width / 2;
            double l = halfWidth - (16 + leftDiameter);//l是公式中心与竖线横坐标的差值。
            splitLine.X1 = splitLine.X2 = 20 + leftDiameter;
            double m = Math.Sqrt(rOfOutEllipse * rOfOutEllipse - l * l);//m线高的一关。
            splitLine.Y1 = halfHeight - m;
            splitLine.Y2 = halfHeight + m;
        }

        protected override void BuildChildren()
        {
            base.BuildChildren();

            if (this.XmlData == null) return;

            XmlNodeList childrenNodes = this.XmlData.SelectNodes("Expression");

            if (childrenNodes == null || childrenNodes.Count <= 0) return;

            foreach (XmlNode node in childrenNodes)
            {
                XmlAttribute attrOfLocation = node.GetAttribute("Location");
                if (attrOfLocation == null) continue;

                switch (attrOfLocation.Value)
                {
                    case "Left":
                        {
                            if (leftPanel != null) leftPanel.XmlData = node; break;
                        }
                    case "Right":
                        {
                            if (rightPanel != null) rightPanel.XmlData = node; break;
                        }
                }
            }

            XmlAttribute attrOfJustContradict = this.XmlData.GetAttribute("IsJustContradict");
            if (attrOfJustContradict != null)
            {
                this.isJustContradict = Boolean.Parse(attrOfJustContradict.Value);
                if (isJustContradict)
                {
                    splitLine.Visibility = Visibility.Visible;
                    leftEllipse.Visibility = Visibility.Hidden;
                    rightEllipse.Visibility = Visibility.Hidden;
                }
                else
                {
                    splitLine.Visibility = Visibility.Hidden;
                    leftEllipse.Visibility = Visibility.Visible;
                    rightEllipse.Visibility = Visibility.Visible;
                }
            }

            RefreshSubPanelRelatios();//防止“隐藏附属面板”字段值被修改后未刷新。
        }

        private SubPanel leftPanel;

        public SubPanel LeftPanel
        {
            get { return leftPanel; }
        }

        private SubPanel rightPanel;

        public SubPanel RightPanel
        {
            get { return rightPanel; }
        }

        protected override void RefreshSubPanelRelatios()
        {
            this.SubPanels.Clear();// 此方法可能被重复调用。

            this.subPanels.Add(leftPanel);
            this.subPanels.Add(rightPanel);

            this.leftPanel.RightSubPanel = rightPanel;
            this.rightPanel.LeftSubPanel = leftPanel;

            this.firstSubPanel = this.leftPanel;
            this.lastSubPanel = this.rightPanel;
        }

        public override void SetProperty(string propertyName, string value)
        {
            base.SetProperty(propertyName, value);

            switch (propertyName)
            {
                case "IsJustContradict":
                    {
                        this.IsJustContradict = bool.Parse(value);
                        break;
                    }
            }
        }
    }
}
